package com.lanf.generator;

import com.lanf.system.exception.LanfException;
import org.springframework.util.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author tanlingfei
 * @version 1.0
 * @description TODO
 * @date 2023-05-30 22:21:19
 */
public class Generator {
    public static void generatOne(CodeVo codeVo) {
        String connectionURL = codeVo.getConnectionURL();
        String username = codeVo.getUsername();
        String password = codeVo.getPassword();
        String driverName = codeVo.getDriverName();
        String tabName = codeVo.getTabName(); //生成表
        String packageName = codeVo.getPackageName();//对应包名 根据包名生成路径

        String filePath = codeVo.getFilePath();  //生成代码存放目录
        filePath = filePath.replaceAll("\\\\", "/");
      /*  String replacement = new SimpleDateFormat("yyyy-MMdd-HHmm-ssSSS").format(new Date());
        String rstr = "/";
        int firstIndex = filePath.indexOf(rstr);
        int secondIndex = filePath.indexOf(rstr, firstIndex + 1);
        if (secondIndex != -1) {
            filePath = filePath.substring(0, secondIndex) + rstr + replacement + rstr + filePath.substring(secondIndex + 1);
        } else {
            if (filePath.length() > firstIndex + 1) {
                filePath = filePath + rstr + replacement;
            } else {
                filePath = filePath.replaceFirst(rstr, rstr + replacement);
            }
        }*/

        String frontPath = codeVo.getFrontPath();  //前端生成代码存放目录
        frontPath = frontPath.replaceAll("\\\\", "/");
    /*    firstIndex = frontPath.indexOf(rstr);
        secondIndex = frontPath.indexOf(rstr, firstIndex + 1);
        if (secondIndex != -1) {
            frontPath = frontPath.substring(0, secondIndex) + rstr + replacement + rstr + frontPath.substring(secondIndex + 1);
        } else {
            if (frontPath.length() > firstIndex + 1) {
                frontPath = frontPath + rstr + replacement;
            } else {
                frontPath = frontPath.replaceFirst(rstr, rstr + replacement);
            }
        }*/
        //final String ftlPath = codeVo.getFtlPath(); //模板文件目录
        final String ftlPath = System.getProperty("user.dir") + "/src/main/resources/template/"; //模板文件目录
        String author = codeVo.getAuthor();
        List<String> genList = codeVo.getGenList();
        try {
            Map map = DbUtil.n(connectionURL, username, password, driverName).getTableInfo(tabName, codeVo.getGenType());
            map.put("isGenDept", "false");
            map.put("genType", codeVo.getGenType());
            //isGenLeftDept 是否生成左侧部门导航 需要表中存在dept_id 或者指定中间表 中间表中存在dept_id
            map.put("isGenLeftDept", codeVo.getIsGenLeftDept());
            //isLazyDept 是否懒加载部门数据 ,点击一层加载一层数据
            map.put("isLazyDept", codeVo.getIsLazyDept());
            map.put("isGenDeptMul", "false");
            map.put("packageName", packageName);
            String packageSub = "";
            String parr[] = packageName.split("\\.");
            if (parr.length < 3) {
                throw new LanfException(5240, "生成包路径必须2层以上");
            }
            map.put("packageSub", parr[2]);
            map.put("author", author);
            map.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            String path = packageName.replaceAll("\\.", "/");
            List<CodeListVo> rules = codeVo.getMulList();
            if (rules != null && rules.size() > 0) { //判断是不是弹窗选择页面 需要生成
                List<TableVo> properties = (List<TableVo>) map.get("data");
                List<String> dataTmp = new ArrayList<>();
                List<String> dataTmp2 = new ArrayList<>();
                for (CodeListVo r : rules) {
                    String mod = r.getMod();
                    String target = r.getTarget();
                    String data = r.getData();
                    String isReapted = "false";
                    String isViewReapted = "false";
                    if (dataTmp.contains(data)) {
                        isReapted = "true";
                    }
                    if (dataTmp2.contains(data)) {
                        isViewReapted = "true";
                    }
                    String key = r.getKey();
                    String value = r.getValue();
                    String modRemark = r.getModRemark();
                    String where = r.getWhere();
                    String pageDir = r.getPageDir();
                    String isMul = r.getIsMul();
                    String mulTable = r.getMulTable();
                    String mulMainColum = r.getMulMainColum();
                    String mulSecColum = r.getMulSecColum();
                    DbUtil dbUtil = DbUtil.n(connectionURL, username, password, driverName);
                    Map map2 = dbUtil.getTableInfo(data, null);
                    map2.put("packageName", packageName);
                    map2.put("packageSub", packageName.split("\\.")[2]);
                    map2.put("author", author);
                    map2.put("createTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    //弹窗变量
                    map2.put("modelNameMv", map.get("modelName"));
                    map2.put("modelNameMv2", map.get("modelName2"));
                    map2.put("modRemark", modRemark);
                    map2.put("modTarget", target);
                    map2.put("modKey", key);
                    map2.put("modValue", value);
                    map2.put("pageDir", pageDir);
                    if (mulMainColum != null) {
                        map2.put("mulMainColum", Utils.lineToHump(mulMainColum));
                    }
                    List<TableVo> targetList = (List<TableVo>) map2.get("data");
                    //设置TableVo添加数据方式
                    for (TableVo v : properties) {//根据关联表字段找到主表字段，然后设置主表字段的显示相关信息
                        // TableVo mv = v;
                        if (v.getColumeName().equals(target)) {
                            v.setMod(mod);
                            v.setModModule("" + map2.get("modelName"));
                            v.setModModule2("" + map2.get("modelName2"));
                            v.setModColKey(key);
                            v.setModColValue(value);
                            v.setModKey(Utils.lineToHump(key));
                            v.setModValue(Utils.lineToHump(value));
                            v.setModRemark(modRemark);
                            v.setModTable(data);
                            //多选设置
                            v.setIsMul(isMul != null ? isMul : "false");
                            v.setMulTableData(mulTable);
                            v.setMulTable2(Utils.lineToHump(mulTable));
                            v.setMulTable(Utils.toFirstUpper(v.getMulTable2()));
                            v.setMulMainColumData(mulMainColum);
                            v.setMulMainColum(Utils.lineToHump(mulMainColum));
                            v.setMulUpperMainColum(Utils.toFirstUpper(v.getMulMainColum()));
                            v.setMulSecColumData(mulSecColum);
                            v.setMulSecColum(Utils.lineToHump(mulSecColum));
                            v.setMulUpperSecColum(Utils.toFirstUpper(v.getMulSecColum()));
                            v.setIsReapted(isReapted);
                            v.setIsViewReapted(isViewReapted);
                            //从目标表找到显示值的相关信息
                            for (TableVo v2 : targetList) {
                                if (v2.getColumeName().equals(value)) {
                                    v.setModValueReamrk(v2.getRemarks());
                                    v.setModValueAlias(Utils.lineToHump(v.getColumeName().split("_")[0] + "_name"));
                                }
                                //这里设置对应弹窗的时候的列表不要显示id,显示id对应表的名称
                                if (v2.getColumeName().toLowerCase().indexOf("_id") > -1) {
                                    v2.setMod("hello");
                                    v2.setModValueReamrk(v2.getRemarks().toLowerCase().replace("id", "") + "名称");
                                    v2.setModValueAlias(Utils.lineToHump(v2.getColumeName().split("_")[0] + "_name"));
                                }
                            }
                            if (pageDir != null && !"".equals(pageDir)) {
                                v.setPageDir(pageDir);
                            } else {
                                v.setPageDir("" + map2.get("packageSub"));
                            }
                            if (!StringUtils.isEmpty(where)) {
                                where = "" + JsonUtil.convertUnderlineToCamelCase(where);
                            }

                            v.setWhere(where);
                            if (where != null && !"".equals(where) && !"null".equals(where)) {
                                v.setWhereName("X" + where.replace(":", "").replace("{", "").replace("}", "").replace("\"", "").trim());
                            } else {
                                String randStr = "X" + UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
                                v.setWhereName(randStr);
                            }
                            if ("id".equals(target) && "true".equals(isMul)) { //id 关联的是中间表，需要对应多个rule规则
                                // v = new TableVo(mv);
                                v.getMulTableVoList().add(new TableVo(v));
                            }
                        }
                    }
                    String vfName = "view.ftl";
                    String vfPath = "View.vue";
                    String vsName = "viewDialog.ftl";
                    String vsPath = "ViewDialog.vue";
                    if ("false".equals(isReapted) && "pop".equals(mod) && !"dept_id".equals(target) && !"deptId".equals(target)) { //生成对应关联表的弹窗选择 如果是部门不需要生成，直接调用树形组件
                        String fName = null;
                        String sName = null;
                        String sPath = null;
                        String fPath = null;
                        if ("true".equals(isMul)) {
                            fName = "select.ftl";
                            sName = "selectDialog.ftl";
                            fPath = "Select.vue";
                            sPath = "SelectDialog.vue";
                        } else {
                            fName = "selectOne.ftl";
                            sName = "selectOneDialog.ftl";
                            fPath = "SelectOne.vue";
                            sPath = "SelectOneDialog.vue";
                        }
                        if ("dept_id".equals(mulSecColum)) {
                            map.put("isGenDept", "true");
                            map.put("isGenDeptMul", "true");
                        }
                        // Freemarker.printFile(vfName, map2, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + map2.get("modelName") + vfPath, frontPath, ftlPath);
                        //Freemarker.printFile(vsName, map2, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + map2.get("modelName") + vsPath, frontPath, ftlPath);
                        if (genList.contains("vue")) {
                            Freemarker.printFile(fName, map2, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + map2.get("modelName") + fPath, frontPath, ftlPath);
                            Freemarker.printFile(sName, map2, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + map2.get("modelName") + sPath, frontPath, ftlPath);
                        }
                    } else if ("pop".equals(mod) && ("dept_id".equals(target) || "deptId".equals(target))) {
                        map.put("isGenDept", "true");
                        map.put("isGenDeptMul", "false");
                    }
                    if ("false".equals(isViewReapted) && "true".equals(isMul)) {
                        dataTmp2.add(data);
                        if (!"sys_dic_item".equals(data)) {
                            if (genList.contains("vue")) {
                                Freemarker.printFile(vfName, map2, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + map2.get("modelName") + vfPath, frontPath, ftlPath);
                                Freemarker.printFile(vsName, map2, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + map2.get("modelName") + vsPath, frontPath, ftlPath);
                            }
                        }
                    }
                    dataTmp.add(data);
                }
            }
            //前段apijs
            if (genList.contains("api"))
                Freemarker.printFile("api.ftl", map, "api/" + map.get("packageSub") + "/" + map.get("modelName2") + ".js", frontPath, ftlPath);
            //前段页面
            if (genList.contains("vue"))
                Freemarker.printFile("list.ftl", map, "views/pages/" + map.get("packageSub") + "/" + map.get("modelName2") + ".vue", frontPath, ftlPath);
            //Vo类生成
            if (genList.contains("vo")) {
                Freemarker.printFile("vo.ftl", map, "java/" + path + "/vo/" + map.get("modelName") + "QueryVo.java", filePath, ftlPath);
                Freemarker.printFile("exp_vo.ftl", map, "java/" + path + "/vo/" + map.get("modelName") + "ExportVo.java", filePath, ftlPath);
            }
            //实体类生成
            if (genList.contains("po"))
                Freemarker.printFile("po.ftl", map, "java/" + path + "/model/" + map.get("modelName") + ".java", filePath, ftlPath);
            //mapper层生成
            if (genList.contains("mapper"))
                Freemarker.printFile("mapper.ftl", map, "java/" + path + "/mapper/" + map.get("modelName") + "Mapper.java", filePath, ftlPath);
            //mapper层xml生成
            if (genList.contains("xml"))
                Freemarker.printFile("mapperXml.ftl", map, "resources/mapper/" + map.get("modelName") + "Mapper.xml", filePath, ftlPath);
            //Service层生成
            if (genList.contains("service"))
                Freemarker.printFile("service.ftl", map, "java/" + path + "/service/" + map.get("modelName") + "Service.java", filePath, ftlPath);
            //Service实现层生成
            if (genList.contains("impl"))
                Freemarker.printFile("service_impl.ftl", map, "java/" + path + "/service/impl/" + map.get("modelName") + "ServiceImpl.java", filePath, ftlPath);
            //Controller层生成
            if (genList.contains("controller"))
                Freemarker.printFile("controller.ftl", map, "java/" + path + "/controller/" + map.get("modelName") + "Controller.java", filePath, ftlPath);
//            //启动类
            if (genList.contains("main")) {
                String mainName = packageName.substring(packageName.lastIndexOf(".") + 1).substring(0, 1).toUpperCase() + packageName.substring(packageName.lastIndexOf(".") + 1).substring(1);
                map.put("mainName", mainName);
                Freemarker.printFile("main.ftl", map, "java/" + path + "/" + mainName + "Application.java", filePath, ftlPath);
            }
        } catch (LanfException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new LanfException(8420, "代码生成失败，请检查配置信息是否填写正确");
        }
    }

}
